/*     */ package com.zimbra.cs.service.mail;
/*     */ 
/*     */ import com.zimbra.common.calendar.ParsedDateTime;
/*     */ import com.zimbra.common.calendar.ZCalendar.ICalTok;
/*     */ import com.zimbra.common.calendar.ZCalendar.ZComponent;
/*     */ import com.zimbra.common.calendar.ZCalendar.ZProperty;
/*     */ import com.zimbra.common.calendar.ZCalendar.ZVCalendar;
/*     */ import com.zimbra.common.service.ServiceException;
/*     */ import com.zimbra.common.soap.Element;
/*     */ import com.zimbra.common.util.ByteUtil;
/*     */ import com.zimbra.common.util.L10nUtil;
/*     */ import com.zimbra.common.util.L10nUtil.MsgKey;
/*     */ import com.zimbra.common.util.Log;
/*     */ import com.zimbra.common.util.MailUtil;
/*     */ import com.zimbra.common.util.ZimbraLog;
/*     */ import com.zimbra.common.zmime.ZSharedFileInputStream;
/*     */ import com.zimbra.cs.account.Account;
/*     */ import com.zimbra.cs.mailbox.CalendarItem;
/*     */ import com.zimbra.cs.mailbox.MailItem.Type;
/*     */ import com.zimbra.cs.mailbox.MailSender;
/*     */ import com.zimbra.cs.mailbox.MailServiceException;
/*     */ import com.zimbra.cs.mailbox.Mailbox;
/*     */ import com.zimbra.cs.mailbox.Mailbox.AddInviteData;
/*     */ import com.zimbra.cs.mailbox.MailboxLock;
/*     */ import com.zimbra.cs.mailbox.OperationContext;
/*     */ import com.zimbra.cs.mailbox.calendar.CalendarMailSender;
/*     */ import com.zimbra.cs.mailbox.calendar.Invite;
/*     */ import com.zimbra.cs.mailbox.calendar.RecurId;
/*     */ import com.zimbra.cs.mailbox.calendar.ZAttendee;
/*     */ import com.zimbra.cs.mime.MPartInfo;
/*     */ import com.zimbra.cs.mime.Mime;
/*     */ import com.zimbra.cs.mime.Mime.FixedMimeMessage;
/*     */ import com.zimbra.cs.mime.ParsedMessage;
/*     */ import com.zimbra.cs.service.util.ItemId;
/*     */ import com.zimbra.cs.service.util.ItemIdFormatter;
/*     */ import com.zimbra.cs.util.AccountUtil;
/*     */ import com.zimbra.cs.util.JMSession;
/*     */ import com.zimbra.soap.ZimbraSoapContext;
/*     */ import java.io.File;
/*     */ import java.io.FileOutputStream;
/*     */ import java.io.IOException;
/*     */ import java.io.InputStream;
/*     */ import java.io.OutputStream;
/*     */ import java.io.PrintStream;
/*     */ import java.util.ArrayList;
/*     */ import java.util.Iterator;
/*     */ import java.util.LinkedList;
/*     */ import java.util.List;
/*     */ import java.util.Locale;
/*     */ import java.util.Queue;
/*     */ import javax.mail.Address;
/*     */ import javax.mail.Message.RecipientType;
/*     */ import javax.mail.MessagingException;
/*     */ import javax.mail.SendFailedException;
/*     */ import javax.mail.internet.InternetAddress;
/*     */ import javax.mail.internet.MimeMessage;
/*     */ import javax.mail.internet.MimePart;
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ public abstract class CalendarRequest
/*     */   extends MailDocumentHandler
/*     */ {
/*  78 */   private MailItem.Type type = MailItem.Type.UNKNOWN;
/*     */   
/*  80 */   protected MailItem.Type getItemType() { return this.type; }
/*     */   
/*     */   public CalendarRequest()
/*     */   {
/*  84 */     if ((this instanceof AppointmentRequest)) {
/*  85 */       this.type = MailItem.Type.APPOINTMENT;
/*  86 */     } else if ((this instanceof TaskRequest)) {
/*  87 */       this.type = MailItem.Type.TASK;
/*     */     }
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   protected static CalSendData handleMsgElement(ZimbraSoapContext zsc, OperationContext octxt, Element msgElem, Account acct, Mailbox mbox, ParseMimeMessage.InviteParser inviteParser)
/*     */     throws ServiceException
/*     */   {
/* 117 */     CalSendData csd = new CalSendData();
/*     */     
/* 119 */     assert (inviteParser.getResult() == null);
/*     */     
/*     */ 
/*     */ 
/* 123 */     String origId = msgElem.getAttribute("origid", null);
/* 124 */     csd.mOrigId = (origId == null ? null : new ItemId(origId, zsc));
/* 125 */     csd.mReplyType = msgElem.getAttribute("rt", MailSender.MSGTYPE_REPLY);
/* 126 */     csd.mIdentityId = msgElem.getAttribute("idnt", null);
/*     */     
/*     */ 
/* 129 */     csd.mMm = ParseMimeMessage.parseMimeMsgSoap(zsc, octxt, mbox, msgElem, null, inviteParser, csd);
/*     */     
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/* 135 */     assert (inviteParser.getResult() != null);
/*     */     
/* 137 */     csd.mInvite = inviteParser.getResult().mInvite;
/*     */     
/* 139 */     return csd;
/*     */   }
/*     */   
/*     */   protected static String getOrigHtml(MimeMessage mm, String defaultCharset) throws ServiceException {
/*     */     try {
/* 144 */       for (MPartInfo mpi : Mime.getParts(mm)) {
/* 145 */         if (mpi.getContentType().equals("text/html"))
/* 146 */           return Mime.getStringContent(mpi.getMimePart(), defaultCharset);
/*     */       }
/* 148 */       return null;
/*     */     } catch (IOException e) {
/* 150 */       throw ServiceException.FAILURE("IOException " + e, e);
/*     */     } catch (MessagingException e) {
/* 152 */       throw ServiceException.FAILURE("MessagingException " + e, e);
/*     */     }
/*     */   }
/*     */   
/*     */   protected static void patchCalendarURLs(MimeMessage mm, String htmlStr, String localURL, String orgAddress, String uid, String attendee, String invId) throws ServiceException
/*     */   {
/*     */     try {
/* 159 */       boolean changed = false;
/*     */       
/* 161 */       String accept = buildUrl(localURL, orgAddress, uid, attendee, invId, "ACCEPT");
/* 162 */       String decline = buildUrl(localURL, orgAddress, uid, attendee, invId, "DECLINE");
/* 163 */       String tentative = buildUrl(localURL, orgAddress, uid, attendee, invId, "TENTATIVE");
/*     */       
/* 165 */       for (MPartInfo mpi : Mime.getParts(mm)) {
/* 166 */         if (mpi.getContentType().equals("text/html")) {
/* 167 */           String str = htmlStr;
/*     */           
/* 169 */           str = str.replaceFirst("href=\"@@ACCEPT@@\"", accept);
/* 170 */           str = str.replaceFirst("href=\"@@DECLINE@@\"", decline);
/* 171 */           str = str.replaceFirst("href=\"@@TENTATIVE@@\"", tentative);
/*     */           
/* 173 */           System.out.println(str);
/* 174 */           mpi.getMimePart().setContent(str, "text/html");
/* 175 */           changed = true;
/*     */           
/* 177 */           break;
/*     */         }
/*     */       }
/*     */       
/* 181 */       if (changed) {
/* 182 */         mm.saveChanges();
/*     */       }
/*     */     } catch (IOException e) {
/* 185 */       throw ServiceException.FAILURE("IOException " + e, e);
/*     */     } catch (MessagingException e) {
/* 187 */       throw ServiceException.FAILURE("MessagingException " + e, e);
/*     */     }
/*     */   }
/*     */   
/*     */   protected static String buildUrl(String localURL, String orgAddress, String uid, String attendee, String invId, String verb)
/*     */   {
/* 193 */     StringBuffer toRet = new StringBuffer("href=\"").append(localURL);
/* 194 */     toRet.append("/service/pubcal/reply?org=").append(orgAddress);
/* 195 */     toRet.append("&uid=").append(uid);
/* 196 */     toRet.append("&at=").append(attendee);
/* 197 */     toRet.append("&v=").append(verb);
/* 198 */     toRet.append("&invId=").append(invId);
/* 199 */     toRet.append('"');
/*     */     
/* 201 */     return toRet.toString();
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   protected static Element sendCalendarMessage(ZimbraSoapContext zsc, OperationContext octxt, int apptFolderId, Account acct, Mailbox mbox, CalSendData csd, Element response, MailSendQueue sendQueue)
/*     */     throws ServiceException
/*     */   {
/* 214 */     return sendCalendarMessage(zsc, octxt, apptFolderId, acct, mbox, csd, response, true, true, sendQueue);
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   protected static Element sendCalendarMessage(ZimbraSoapContext zsc, OperationContext octxt, int apptFolderId, Account acct, Mailbox mbox, CalSendData csd, Element response, boolean updateOwnAppointment, boolean forceSend, MailSendQueue sendQueue)
/*     */     throws ServiceException
/*     */   {
/* 229 */     return sendCalendarMessageInternal(zsc, octxt, apptFolderId, acct, mbox, csd, response, updateOwnAppointment, forceSend, sendQueue);
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   private static final long MSECS_PER_DAY = 86400000L;
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   protected static Element sendCalendarCancelMessage(ZimbraSoapContext zsc, OperationContext octxt, int apptFolderId, Account acct, Mailbox mbox, CalSendData csd, boolean cancelOwnAppointment, MailSendQueue sendQueue)
/*     */     throws ServiceException
/*     */   {
/* 260 */     return sendCalendarMessageInternal(zsc, octxt, apptFolderId, acct, mbox, csd, null, cancelOwnAppointment, true, sendQueue);
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   private static Element sendCalendarMessageInternal(ZimbraSoapContext zsc, OperationContext octxt, int apptFolderId, Account acct, Mailbox mbox, CalSendData csd, Element response, boolean updateOwnAppointment, boolean forceSend, MailSendQueue sendQueue)
/*     */     throws ServiceException
/*     */   {
/* 290 */     boolean onBehalfOf = isOnBehalfOfRequest(zsc);
/* 291 */     boolean notifyOwner = (onBehalfOf) && (acct.getBooleanAttr("zimbraPrefCalendarNotifyDelegatedChanges", false));
/* 292 */     if (notifyOwner) {
/*     */       try {
/* 294 */         InternetAddress addr = AccountUtil.getFriendlyEmailAddress(acct);
/* 295 */         csd.mMm.addRecipient(Message.RecipientType.TO, addr);
/*     */       } catch (MessagingException e) {
/* 297 */         throw ServiceException.FAILURE("count not add calendar owner to recipient list", e);
/*     */       }
/*     */     }
/*     */     
/*     */ 
/*     */ 
/* 303 */     if (!onBehalfOf) {
/* 304 */       String[] aliases = acct.getMailAlias();
/*     */       String[] addrs;
/* 306 */       if ((aliases != null) && (aliases.length > 0)) {
/* 307 */         String[] addrs = new String[aliases.length + 1];
/* 308 */         addrs[0] = acct.getAttr("mail");
/* 309 */         for (int i = 0; i < aliases.length; i++) {
/* 310 */           addrs[(i + 1)] = aliases[i];
/*     */         }
/*     */       } else {
/* 313 */         addrs = new String[1];
/* 314 */         addrs[0] = acct.getAttr("mail");
/*     */       }
/*     */       try {
/* 317 */         Mime.removeRecipients(csd.mMm, addrs);
/*     */       }
/*     */       catch (MessagingException e) {}
/*     */     }
/* 321 */     ParsedMessage pm = new ParsedMessage(csd.mMm, false);
/*     */     
/* 323 */     if ((csd.mInvite.getFragment() == null) || (csd.mInvite.getFragment().equals(""))) {
/* 324 */       csd.mInvite.setFragment(pm.getFragment(acct.getLocale()));
/*     */     }
/*     */     
/* 327 */     boolean willNotify = false;
/* 328 */     if (!csd.mDontNotifyAttendees) {
/*     */       try {
/* 330 */         Address[] rcpts = csd.mMm.getAllRecipients();
/* 331 */         willNotify = (rcpts != null) && (rcpts.length > 0);
/*     */       } catch (MessagingException e) {
/* 333 */         throw ServiceException.FAILURE("Checking recipients of outgoing msg ", e);
/*     */       }
/*     */     }
/*     */     
/*     */ 
/* 338 */     if ((!csd.mInvite.isCancel()) && (!forceSend) && (willNotify)) {
/*     */       try {
/* 340 */         MailUtil.validateRcptAddresses(JMSession.getSmtpSession(mbox.getAccount()), csd.mMm.getAllRecipients());
/*     */       } catch (MessagingException mex) {
/* 342 */         if ((mex instanceof SendFailedException)) {
/* 343 */           SendFailedException sfex = (SendFailedException)mex;
/* 344 */           throw MailServiceException.SEND_ABORTED_ADDRESS_FAILURE("invalid addresses", sfex, sfex.getInvalidAddresses(), sfex.getValidUnsentAddresses());
/*     */         }
/*     */       }
/*     */     }
/*     */     
/* 349 */     Mailbox.AddInviteData aid = null;
/* 350 */     File tempMmFile = null;
/* 351 */     boolean queued = false;
/*     */     try {
/* 353 */       if (willNotify)
/*     */       {
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/* 363 */         OutputStream os = null;
/* 364 */         InputStream is = null;
/*     */         try {
/* 366 */           tempMmFile = File.createTempFile("zcal", "tmp");
/*     */           
/* 368 */           os = new FileOutputStream(tempMmFile);
/* 369 */           csd.mMm.writeTo(os);
/* 370 */           ByteUtil.closeStream(os);
/* 371 */           os = null;
/*     */           
/* 373 */           is = new ZSharedFileInputStream(tempMmFile);
/* 374 */           csd.mMm = new Mime.FixedMimeMessage(JMSession.getSmtpSession(acct), is);
/*     */         } catch (IOException e) {
/* 376 */           if (tempMmFile != null)
/* 377 */             tempMmFile.delete();
/* 378 */           throw ServiceException.FAILURE("error creating calendar message content", e);
/*     */         } catch (MessagingException e) {
/* 380 */           if (tempMmFile != null)
/* 381 */             tempMmFile.delete();
/* 382 */           throw ServiceException.FAILURE("error creating calendar message content", e);
/*     */         } finally {
/* 384 */           ByteUtil.closeStream(os);
/* 385 */           ByteUtil.closeStream(is);
/*     */         }
/*     */       }
/*     */       
/*     */ 
/*     */ 
/* 391 */       if (updateOwnAppointment) {
/* 392 */         aid = mbox.addInvite(octxt, csd.mInvite, apptFolderId, pm);
/*     */       }
/*     */       
/*     */ 
/* 396 */       if (willNotify) {
/* 397 */         MailSendQueueEntry entry = new MailSendQueueEntry(octxt, mbox, csd, tempMmFile);
/* 398 */         sendQueue.add(entry);
/* 399 */         queued = true;
/*     */       }
/*     */     }
/*     */     finally {
/* 403 */       if ((tempMmFile != null) && (!queued)) {
/* 404 */         tempMmFile.delete();
/*     */       }
/*     */     }
/*     */     
/* 408 */     if ((updateOwnAppointment) && (response != null) && (aid != null)) {
/* 409 */       csd.mAddInvData = aid;
/* 410 */       ItemIdFormatter ifmt = new ItemIdFormatter(zsc);
/* 411 */       String id = ifmt.formatItemId(aid.calItemId);
/* 412 */       response.addAttribute("calItemId", id);
/* 413 */       if (csd.mInvite.isEvent())
/* 414 */         response.addAttribute("apptId", id);
/* 415 */       response.addAttribute("invId", ifmt.formatItemId(aid.calItemId, aid.invId));
/* 416 */       if (Invite.isOrganizerMethod(csd.mInvite.getMethod())) {
/* 417 */         response.addAttribute("ms", aid.modSeq);
/* 418 */         response.addAttribute("rev", aid.rev);
/*     */       }
/*     */     }
/*     */     
/* 422 */     return response;
/*     */   }
/*     */   
/*     */   protected static Element echoAddedInvite(Element parent, ItemIdFormatter ifmt, OperationContext octxt, Mailbox mbox, Mailbox.AddInviteData aid, int maxSize, boolean wantHtml, boolean neuter)
/*     */     throws ServiceException
/*     */   {
/* 428 */     CalendarItem calItem = mbox.getCalendarItemById(octxt, aid.calItemId);
/* 429 */     Invite inv = calItem.getInvite(aid.invId, aid.compNum);
/* 430 */     String recurIdZ = null;
/* 431 */     if ((inv != null) && (inv.getRecurId() != null))
/* 432 */       recurIdZ = inv.getRecurId().getDtZ();
/* 433 */     ItemId iid = new ItemId(calItem, aid.invId);
/* 434 */     Element echoElem = parent.addElement("echo");
/* 435 */     ToXML.encodeInviteAsMP(echoElem, ifmt, octxt, calItem, recurIdZ, iid, null, maxSize, wantHtml, neuter, null, false, false);
/* 436 */     return echoElem;
/*     */   }
/*     */   
/*     */   protected static void sendOrganizerChangeMessage(ZimbraSoapContext zsc, OperationContext octxt, CalendarItem calItem, Account acct, Mailbox mbox, MailSendQueue sendQueue)
/*     */   {
/*     */     try {
/* 442 */       Account authAccount = getAuthenticatedAccount(zsc);
/* 443 */       Invite[] invites = calItem.getInvites();
/* 444 */       for (Invite inv : invites) {
/* 445 */         List<Address> rcpts = CalendarMailSender.toListFromAttendees(inv.getAttendees());
/* 446 */         if (rcpts.size() > 0) {
/* 447 */           CalSendData csd = new CalSendData();
/* 448 */           csd.mInvite = inv;
/* 449 */           csd.mOrigId = new ItemId(mbox, inv.getMailItemId());
/* 450 */           csd.mMm = CalendarMailSender.createOrganizerChangeMessage(acct, authAccount, zsc.isUsingAdminPrivileges(), calItem, csd.mInvite, rcpts);
/*     */           
/* 452 */           sendCalendarMessageInternal(zsc, octxt, calItem.getFolderId(), acct, mbox, csd, null, false, true, sendQueue);
/*     */         }
/*     */       }
/*     */     }
/*     */     catch (ServiceException e) {
/* 457 */       ZimbraLog.calendar.warn("Ignoring error while sending organizer change message", e);
/*     */     }
/*     */   }
/*     */   
/*     */   private static String getAttendeesAddressList(List<ZAttendee> list) {
/* 462 */     StringBuilder sb = new StringBuilder();
/* 463 */     int i = 0;
/* 464 */     for (ZAttendee a : list) {
/* 465 */       if (i > 0) sb.append(", ");
/* 466 */       sb.append(a.getAddress());
/*     */     }
/* 468 */     return sb.toString();
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   protected static boolean inviteIsAfterTime(Invite inv, long time)
/*     */   {
/* 477 */     long startUtc = 0L;
/* 478 */     ParsedDateTime dtStart = inv.getStartTime();
/* 479 */     if (dtStart != null)
/* 480 */       startUtc = dtStart.getUtcTime();
/* 481 */     long ridUtc = 0L;
/* 482 */     RecurId rid = inv.getRecurId();
/* 483 */     if (rid != null) {
/* 484 */       ParsedDateTime ridDt = rid.getDt();
/* 485 */       if (ridDt != null)
/* 486 */         ridUtc = ridDt.getUtcTime();
/*     */     }
/* 488 */     long invTime = Math.max(startUtc, ridUtc);
/* 489 */     if (inv.isAllDayEvent())
/* 490 */       time -= 86400000L;
/* 491 */     return invTime >= time;
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   protected static void notifyCalendarItem(ZimbraSoapContext zsc, OperationContext octxt, Account acct, Mailbox mbox, CalendarItem calItem, boolean notifyAllAttendees, List<ZAttendee> addedAttendees, boolean ignorePastExceptions, MailSendQueue sendQueue)
/*     */     throws ServiceException
/*     */   {
/* 501 */     boolean onBehalfOf = isOnBehalfOfRequest(zsc);
/* 502 */     Account authAcct = getAuthenticatedAccount(zsc);
/* 503 */     boolean hidePrivate = (!calItem.isPublic()) && (!calItem.allowPrivateAccess(authAcct, zsc.isUsingAdminPrivileges()));
/*     */     
/* 505 */     Address from = AccountUtil.getFriendlyEmailAddress(acct);
/* 506 */     Address sender = null;
/* 507 */     if (onBehalfOf)
/* 508 */       sender = AccountUtil.getFriendlyEmailAddress(authAcct);
/* 509 */     List<Address> addedRcpts = CalendarMailSender.toListFromAttendees(addedAttendees);
/*     */     
/* 511 */     long now = octxt != null ? octxt.getTimestamp() : System.currentTimeMillis();
/*     */     
/* 513 */     mbox.lock.lock();
/*     */     
/*     */     try
/*     */     {
/* 517 */       calItem = mbox.getCalendarItemById(octxt, calItem.getId());
/*     */       
/* 519 */       Invite[] invites = calItem.getInvites();
/*     */       
/*     */ 
/* 522 */       List<Invite> exceptions = new ArrayList();
/* 523 */       for (Invite inv : invites) {
/* 524 */         if (inv.hasRecurId()) {
/* 525 */           exceptions.add(inv);
/*     */         }
/*     */       }
/*     */       
/*     */ 
/* 530 */       boolean didExceptions = false;
/* 531 */       for (Invite inv : invites)
/* 532 */         if ((!ignorePastExceptions) || (!inv.hasRecurId()) || (inviteIsAfterTime(inv, now)))
/*     */         {
/*     */ 
/*     */ 
/*     */ 
/* 537 */           ZCalendar.ZVCalendar cal = inv.newToICalendar(!hidePrivate);
/*     */           
/* 539 */           if ((inv.isRecurrence()) && (!didExceptions))
/*     */           {
/* 541 */             ZCalendar.ZComponent seriesComp = null;
/* 542 */             for (Iterator<ZCalendar.ZComponent> compIter = cal.getComponentIterator(); compIter.hasNext();) {
/* 543 */               ZCalendar.ZComponent comp = (ZCalendar.ZComponent)compIter.next();
/* 544 */               ZCalendar.ICalTok compName = comp.getTok();
/* 545 */               if (((ZCalendar.ICalTok.VEVENT.equals(compName)) || (ZCalendar.ICalTok.VTODO.equals(compName))) && 
/* 546 */                 (comp.getProperty(ZCalendar.ICalTok.RRULE) != null)) {
/* 547 */                 seriesComp = comp;
/* 548 */                 break;
/*     */               }
/*     */             }
/*     */             
/* 552 */             for (Invite except : exceptions) {
/* 553 */               if ((except.isCancel()) && (seriesComp != null))
/*     */               {
/* 555 */                 RecurId rid = except.getRecurId();
/* 556 */                 if ((rid != null) && (rid.getDt() != null)) {
/* 557 */                   ZCalendar.ZProperty exdate = rid.getDt().toProperty(ZCalendar.ICalTok.EXDATE, false);
/* 558 */                   seriesComp.addProperty(exdate);
/*     */                 }
/*     */               }
/*     */               else {
/* 562 */                 ZCalendar.ZComponent exceptComp = except.newToVComponent(false, !hidePrivate);
/* 563 */                 cal.addComponent(exceptComp);
/*     */               }
/*     */             }
/* 566 */             didExceptions = true;
/*     */           }
/*     */           
/*     */ 
/* 570 */           MimeMessage mmInv = calItem.getSubpartMessage(inv.getMailItemId());
/*     */           List<Address> rcpts;
/* 572 */           List<Address> rcpts; if (notifyAllAttendees) {
/* 573 */             rcpts = CalendarMailSender.toListFromAttendees(inv.getAttendees());
/*     */           } else {
/* 575 */             rcpts = addedRcpts;
/*     */           }
/* 577 */           if ((rcpts != null) && (!rcpts.isEmpty())) {
/* 578 */             MimeMessage mmModify = CalendarMailSender.createCalendarMessage(authAcct, from, sender, rcpts, mmInv, inv, cal, true);
/* 579 */             CalSendData csd = new CalSendData();
/* 580 */             csd.mMm = mmModify;
/* 581 */             csd.mOrigId = new ItemId(mbox, inv.getMailItemId());
/* 582 */             MailSendQueueEntry entry = new MailSendQueueEntry(octxt, mbox, csd, null);
/* 583 */             sendQueue.add(entry);
/*     */           }
/*     */         }
/*     */     } finally {
/* 587 */       mbox.lock.release();
/*     */     }
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */   protected static void addRemoveAttendeesInExceptions(OperationContext octxt, Mailbox mbox, CalendarItem calItem, List<ZAttendee> toAdd, List<ZAttendee> toRemove, boolean ignorePastExceptions)
/*     */     throws ServiceException
/*     */   {
/* 596 */     mbox.lock.lock();
/*     */     
/*     */     try
/*     */     {
/* 600 */       calItem = mbox.getCalendarItemById(octxt, calItem.getId());
/*     */       
/* 602 */       long now = octxt != null ? octxt.getTimestamp() : System.currentTimeMillis();
/* 603 */       boolean first = true;
/* 604 */       Invite[] invites = calItem.getInvites();
/* 605 */       for (Invite inv : invites)
/*     */       {
/* 607 */         if ((!ignorePastExceptions) || (!inv.hasRecurId()) || (inviteIsAfterTime(inv, now)))
/*     */         {
/*     */ 
/*     */ 
/*     */ 
/* 612 */           boolean modified = false;
/* 613 */           Invite modify = inv.newCopy();
/* 614 */           modify.setMailItemId(inv.getMailItemId());
/* 615 */           List<ZAttendee> existingAts = modify.getAttendees();
/* 616 */           List<ZAttendee> addList = new ArrayList(toAdd);
/* 617 */           for (Iterator<ZAttendee> iter = existingAts.iterator(); iter.hasNext();) {
/* 618 */             ZAttendee existingAt = (ZAttendee)iter.next();
/* 619 */             existingAtEmail = existingAt.getAddress();
/* 620 */             if (existingAtEmail != null)
/*     */             {
/* 622 */               for (Iterator<ZAttendee> iterAdd = addList.iterator(); iterAdd.hasNext();) {
/* 623 */                 ZAttendee at = (ZAttendee)iterAdd.next();
/* 624 */                 if (existingAtEmail.equalsIgnoreCase(at.getAddress())) {
/* 625 */                   iterAdd.remove();
/*     */                 }
/*     */               }
/*     */               
/* 629 */               for (ZAttendee at : toRemove) {
/* 630 */                 if (existingAtEmail.equalsIgnoreCase(at.getAddress())) {
/* 631 */                   iter.remove();
/* 632 */                   modified = true;
/* 633 */                   break;
/*     */                 }
/*     */               }
/*     */             }
/*     */           }
/*     */           String existingAtEmail;
/* 639 */           if (!addList.isEmpty()) {
/* 640 */             for (ZAttendee at : addList) {
/* 641 */               modify.addAttendee(at);
/*     */             }
/* 643 */             modified = true;
/*     */           }
/*     */           
/*     */ 
/* 647 */           if (modified)
/*     */           {
/*     */ 
/* 650 */             if (!modify.isCancel()) {
/* 651 */               modify.setMethod(ZCalendar.ICalTok.REQUEST.toString());
/*     */             }
/* 653 */             modify.setDtStamp(now);
/*     */             
/* 655 */             MimeMessage mmInv = calItem.getSubpartMessage(modify.getMailItemId());
/* 656 */             ParsedMessage pm = mmInv != null ? new ParsedMessage(mmInv, false) : null;
/* 657 */             mbox.addInvite(octxt, modify, calItem.getFolderId(), pm, true, false, first);
/* 658 */             first = false;
/*     */             
/*     */ 
/* 661 */             calItem = mbox.getCalendarItemById(octxt, calItem.getId());
/*     */           }
/*     */         } }
/*     */     } finally {
/* 665 */       mbox.lock.release();
/*     */     }
/*     */   }
/*     */   
/*     */ 
/*     */   protected static void notifyRemovedAttendees(ZimbraSoapContext zsc, OperationContext octxt, Account acct, Mailbox mbox, CalendarItem calItem, Invite invToCancel, List<ZAttendee> removedAttendees, MailSendQueue sendQueue)
/*     */     throws ServiceException
/*     */   {
/* 673 */     boolean onBehalfOf = isOnBehalfOfRequest(zsc);
/* 674 */     Account authAcct = getAuthenticatedAccount(zsc);
/* 675 */     Locale locale = !onBehalfOf ? acct.getLocale() : authAcct.getLocale();
/*     */     
/* 677 */     CalSendData dat = new CalSendData();
/* 678 */     dat.mOrigId = new ItemId(mbox, invToCancel.getMailItemId());
/* 679 */     dat.mReplyType = MailSender.MSGTYPE_REPLY;
/*     */     
/* 681 */     String text = L10nUtil.getMessage(L10nUtil.MsgKey.calendarCancelRemovedFromAttendeeList, locale, new Object[0]);
/*     */     
/* 683 */     if (ZimbraLog.calendar.isDebugEnabled()) {
/* 684 */       StringBuilder sb = new StringBuilder("Sending cancellation message for \"");
/* 685 */       sb.append(invToCancel.getName()).append("\" to ");
/* 686 */       sb.append(getAttendeesAddressList(removedAttendees));
/* 687 */       ZimbraLog.calendar.debug(sb.toString());
/*     */     }
/*     */     
/* 690 */     List<Address> rcpts = CalendarMailSender.toListFromAttendees(removedAttendees);
/*     */     try {
/* 692 */       dat.mInvite = CalendarUtils.buildCancelInviteCalendar(acct, authAcct, zsc.isUsingAdminPrivileges(), onBehalfOf, calItem, invToCancel, text, removedAttendees);
/*     */       
/* 694 */       ZCalendar.ZVCalendar cal = dat.mInvite.newToICalendar(true);
/* 695 */       dat.mMm = CalendarMailSender.createCancelMessage(acct, authAcct, zsc.isUsingAdminPrivileges(), onBehalfOf, rcpts, calItem, invToCancel, text, cal);
/*     */       
/*     */ 
/*     */ 
/* 699 */       if ((!dat.mInvite.isOrganizer()) && (rcpts != null) && (!rcpts.isEmpty())) {
/* 700 */         throw MailServiceException.MUST_BE_ORGANIZER("updateRemovedInvitees");
/*     */       }
/* 702 */       sendCalendarCancelMessage(zsc, octxt, calItem.getFolderId(), acct, mbox, dat, false, sendQueue);
/*     */     } catch (ServiceException ex) {
/* 704 */       String to = getAttendeesAddressList(removedAttendees);
/* 705 */       ZimbraLog.calendar.debug("Could not inform attendees (" + to + ") that they were removed from meeting " + invToCancel.toString() + " b/c of exception: " + ex.toString());
/*     */     }
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   public static boolean isOnBehalfOfRequest(ZimbraSoapContext zsc)
/*     */     throws ServiceException
/*     */   {
/* 720 */     if (!zsc.isDelegatedRequest())
/* 721 */       return false;
/* 722 */     return !AccountUtil.isZDesktopLocalAccount(zsc.getAuthtokenAccountId()); }
/*     */   
/*     */   protected static class CalSendData extends ParseMimeMessage.MimeMessageData { ItemId mOrigId;
/*     */     String mReplyType;
/*     */     String mIdentityId;
/*     */     MimeMessage mMm;
/*     */     Invite mInvite;
/*     */     boolean mDontNotifyAttendees;
/*     */     Mailbox.AddInviteData mAddInvData; }
/*     */   
/* 732 */   protected static class MailSendQueueEntry { MailSendQueueEntry(OperationContext octxt, Mailbox mbox, CalendarRequest.CalSendData csd, File file) { this.octxt = octxt;
/* 733 */       this.mbox = mbox;
/* 734 */       this.csd = csd;
/* 735 */       this.file = file; }
/*     */     
/*     */     OperationContext octxt;
/*     */     Mailbox mbox;
/*     */     CalendarRequest.CalSendData csd;
/*     */     File file;
/* 741 */     public void send() throws ServiceException { try { CalendarMailSender.sendPartial(this.octxt, this.mbox, this.csd.mMm, this.csd.uploads, this.csd.mOrigId, this.csd.mReplyType, this.csd.mIdentityId, false);
/*     */       }
/*     */       finally {
/* 744 */         if (this.file != null) {
/* 745 */           this.file.delete();
/*     */         }
/*     */       }
/*     */     }
/*     */   }
/*     */   
/*     */   protected static class MailSendQueue {
/* 752 */     Queue<CalendarRequest.MailSendQueueEntry> queue = new LinkedList();
/*     */     
/*     */     public void add(CalendarRequest.MailSendQueueEntry entry) {
/* 755 */       this.queue.add(entry);
/*     */     }
/*     */     
/*     */     public void send() {
/* 759 */       while (!this.queue.isEmpty()) {
/* 760 */         CalendarRequest.MailSendQueueEntry entry = (CalendarRequest.MailSendQueueEntry)this.queue.remove();
/* 761 */         if (entry != null) {
/*     */           try {
/* 763 */             entry.send();
/*     */           } catch (ServiceException e) {
/* 765 */             ZimbraLog.calendar.warn("ignoring error while sending calendar email", e);
/*     */           }
/*     */         }
/*     */       }
/*     */     }
/*     */   }
/*     */ }


/* Location:              /home/mint/zimbrastore.jar!/com/zimbra/cs/service/mail/CalendarRequest.class
 * Java compiler version: 7 (51.0)
 * JD-Core Version:       0.7.1
 */